﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using NetMicro.Core.Extensions;
using NetMicro.Core.Helper;
using NetMicro.Core.Ioc.Attributes;
using NetMicro.Domains;
using NetMicro.Domains.Repositories;

namespace NetMicro.MongoProvider
{
    /// <summary>
    /// mongodb仓储
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public class MongoDBRepository<TEntity, TKey> : IMongoDBRepository<TEntity, TKey> where TEntity : EntityBase<TKey>, new()
    {
        private readonly MongoDBContext _context;
        private readonly IMongoTableFactory _multiTableFactory;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="multiTableFactory"></param>
        public MongoDBRepository(MongoDBContext context, IMongoTableFactory multiTableFactory)
        {
            _context = context;
            _multiTableFactory = multiTableFactory;
        }

        /// <summary>
        /// 
        /// </summary>
        private IMongoCollection<TEntity> Client(object obj = null) => _context.GetCollectionInstance<TEntity>(GetTableName(obj));

        /// <summary>
        /// 获取MongoClient
        /// </summary>
        /// <returns></returns>
        public MongoClient GetMongoClient() => _context.Client();

        #region 事务处理

        /// <summary>
        /// 开始事务
        /// </summary>
        /// <returns></returns>
        public IClientSessionHandle StartTransaction()
        {
            IClientSessionHandle session = GetMongoClient().StartSession();
            session.StartTransaction();
            return session;
        }
        /// <summary>
        /// 提交事务
        /// </summary>
        /// <returns></returns>
        public void CommitTransaction(IClientSessionHandle session)
        {
            session.CommitTransaction();
        }
        /// <summary>
        /// 终止事务
        /// </summary>
        /// <returns></returns>
        public void AbortTransaction(IClientSessionHandle session)
        {
            session.AbortTransaction();
        }


        /// <summary>
        /// 开始事务（异步）
        /// </summary>
        /// <returns></returns>
        public async Task<IClientSessionHandle> StartTransactionAsync()
        {
            IClientSessionHandle session = await GetMongoClient().StartSessionAsync();
            session.StartTransaction();
            return session;
        }
        /// <summary>
        /// 提交事务（异步）
        /// </summary>
        /// <returns></returns>
        public async Task CommitTransactionAsync(IClientSessionHandle session)
        {
            await session.CommitTransactionAsync();
        }
        /// <summary>
        /// 终止事务（异步）
        /// </summary>
        /// <returns></returns>
        public async Task AbortTransactionAsync(IClientSessionHandle session)
        {
            await session.AbortTransactionAsync();
        }


        #endregion

        #region 新增


        /// <summary>
        /// 分表插入一条数据(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public TKey Insert(TEntity t, object subTable = null, IClientSessionHandle session = null)
        {
            t.Init();
            if (session == null)
            {
                Client(subTable).InsertOne(t);
            }
            else
            {
                Client(subTable).InsertOne(session, t);
            }
            return t.Id;
        }



        /// <summary>
        /// 分表批量插入(分表)
        /// </summary>
        /// <param name="t">实体集合</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public bool InsertList(List<TEntity> t, object subTable = null, IClientSessionHandle session = null)
        {
            t.ForEach(m => m.Init());
            if (session == null)
            {
                Client(subTable).InsertMany(t);
            }
            else
            {
                Client(subTable).InsertMany(session, t);
            }
            return true;
        }
        /// <summary>
        /// 分表插入一条数据（异步）(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public async Task<TKey> InsertAsync(TEntity t, object subTable = null, IClientSessionHandle session = null)
        {
            t.Init();
            if (session == null)
            {
                await Client(subTable).InsertOneAsync(t);
            }
            else
            {
                await Client(subTable).InsertOneAsync(session, t);
            }
            return t.Id;
        }



        /// <summary>
        /// 分表批量插入（异步）(分表)
        /// </summary>
        /// <param name="t">实体集合</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public async Task<bool> InsertListAsync(List<TEntity> t, object subTable = null, IClientSessionHandle session = null)
        {
            t.ForEach(m => m.Init());
            if (session == null)
            {
                await Client(subTable).InsertManyAsync(t);
            }
            else
            {
                await Client(subTable).InsertManyAsync(session, t);
            }
            return true;
        }
        #endregion 新增

        #region 修改

        /// <summary>
        /// 修改单条数据（异步）(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public bool Update(TEntity t, Expression<Func<TEntity, bool>> filter, object subTable = null, IClientSessionHandle session = null)
        {
            filter = ExpressionIsDelete(filter);
            t.UpdateInit(t);
            //要修改的字段
            List<UpdateDefinition<TEntity>> list = BuildUpdateDefinition(t);
            UpdateDefinition<TEntity> updatefilter = Builders<TEntity>.Update.Combine(list);
            UpdateResult result = null;
            if (session == null)
            {
                result = Client(subTable).UpdateOne(filter, updatefilter);
            }
            else
            {
                result = Client(subTable).UpdateOne(session, filter, updatefilter);
            }

            bool flag = result.IsAcknowledged;
            if (flag)
            {
                flag = result.ModifiedCount > 0;
            }
            return flag;
        }


        /// <summary>
        /// 修改多条数据(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public bool UpdateMany(TEntity t, Expression<Func<TEntity, bool>> filter, object subTable = null, IClientSessionHandle session = null)
        {
            filter = ExpressionIsDelete(filter);
            t.UpdateInit(t);

            //要修改的字段
            List<UpdateDefinition<TEntity>> list = BuildUpdateDefinition(t);
            UpdateDefinition<TEntity> updatefilter = Builders<TEntity>.Update.Combine(list);
            UpdateResult result = null;
            if (session == null)
            {
                result = Client(subTable).UpdateMany(filter, updatefilter);
            }
            else
            {
                result = Client(subTable).UpdateMany(session, filter, updatefilter);
            }

            bool flag = result.IsAcknowledged;
            if (flag)
            {
                flag = result.ModifiedCount > 0;
            }
            return flag;
        }


        /// <summary>
        /// 修改多条数据(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public bool UpdateList(List<TEntity> t, object subTable = null, IClientSessionHandle session = null)
        {
            foreach (TEntity item in t)
            {
                item.UpdateInit(item);
                Update(item, w => w.Id.ToString() == item.Id.ToString(), subTable, session);
            }
            return true;
        }



        /// <summary>
        /// 修改单条数据（异步）(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public async Task<bool> UpdateAsync(TEntity t, Expression<Func<TEntity, bool>> filter, object subTable = null, IClientSessionHandle session = null)
        {
            filter = ExpressionIsDelete(filter);
            t.UpdateInit(t);
            //要修改的字段
            List<UpdateDefinition<TEntity>> list = BuildUpdateDefinition(t);
            UpdateDefinition<TEntity> updatefilter = Builders<TEntity>.Update.Combine(list);
            UpdateResult result = null;
            if (session == null)
            {
                result = await Client(subTable).UpdateOneAsync(filter, updatefilter);
            }
            else
            {
                result = await Client(subTable).UpdateOneAsync(session, filter, updatefilter);
            }

            bool flag = result.IsAcknowledged;
            if (flag)
            {
                flag = result.ModifiedCount > 0;
            }
            return flag;
        }


        /// <summary>
        /// 修改多条数据（异步）(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public async Task<bool> UpdateManyAsync(TEntity t, Expression<Func<TEntity, bool>> filter, object subTable = null, IClientSessionHandle session = null)
        {
            filter = ExpressionIsDelete(filter);
            t.UpdateInit(t);

            //要修改的字段
            List<UpdateDefinition<TEntity>> list = BuildUpdateDefinition(t);
            UpdateDefinition<TEntity> updatefilter = Builders<TEntity>.Update.Combine(list);
            UpdateResult result = null;
            if (session == null)
            {
                result = await Client(subTable).UpdateManyAsync(filter, updatefilter);
            }
            else
            {
                result = await Client(subTable).UpdateManyAsync(session, filter, updatefilter);
            }

            bool flag = result.IsAcknowledged;
            if (flag)
            {
                flag = result.ModifiedCount > 0;
            }
            return flag;
        }


        /// <summary>
        /// 修改多条数据（异步）(分表)
        /// </summary>
        /// <param name="t">添加的实体</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public async Task<bool> UpdateListAsync(List<TEntity> t, object subTable = null, IClientSessionHandle session = null)
        {
            foreach (TEntity item in t)
            {
                item.UpdateInit(item);
                await UpdateAsync(item, w => w.Id.ToString() == item.Id.ToString(), subTable, session);
            }
            return true;
        }

        /// <summary>
        /// 生成更新脚本
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="parent"></param>
        /// <returns></returns>
        private List<UpdateDefinition<TEntity>> BuildUpdateDefinition(object doc, string parent = null)
        {
            List<UpdateDefinition<TEntity>> updateList = new List<UpdateDefinition<TEntity>>();
            foreach (PropertyInfo property in doc.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                string key = parent == null ? property.Name : $"{parent}.{property.Name}";
                //非空的复杂类型
                if ((property.PropertyType.IsClass || property.PropertyType.IsInterface) && property.PropertyType != typeof(string) && property.GetValue(doc) != null)
                {
                    object subObj = property.GetValue(doc);
                    if (typeof(IList).IsAssignableFrom(property.PropertyType))
                    {
                        #region 集合类型

                        int i = 0;
                        foreach (object item in subObj as IList)
                        {
                            Type itemType = item.GetType();
                            if ((itemType.IsClass && itemType.Name != "String") || itemType.IsInterface)
                            {
                                updateList.AddRange(BuildUpdateDefinition(item, $"{key}.{i}"));
                            }
                            else
                            {
                                updateList.Add(Builders<TEntity>.Update.Set(string.Format("{0}.{1}", key, i), item));
                            }
                            i++;
                        }

                        #endregion 集合类型
                    }
                    else if (typeof(BsonDocument).IsAssignableFrom(property.PropertyType))
                    {
                        updateList.Add(Builders<TEntity>.Update.Set(key, subObj));
                    }
                    else
                    {
                        #region 实体类型

                        //复杂类型，导航属性，类文档和集合文档
                        foreach (PropertyInfo sub in property.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
                        {
                            updateList.Add(Builders<TEntity>.Update.Set(string.Format("{0}.{1}", key, sub.Name), sub.GetValue(subObj)));
                        }

                        #endregion 实体类型
                    }
                }
                else //简单类型
                {
                    updateList.Add(Builders<TEntity>.Update.Set(key, property.GetValue(doc)));
                }
            }

            return updateList;
        }
        #endregion 修改

        #region 删除


        /// <summary>
        /// 异步逻辑删除一条数据（异步）(分表)
        /// </summary>
        /// <param name="id">原生Id</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public bool SoftDelete(TKey id, object subTable = null, IClientSessionHandle session = null)
        {
            //删除条件
            FilterDefinition<TEntity> filter = Builders<TEntity>.Filter.Eq("Id", id);
            EntityBase<TKey> entity = new EntityBase<TKey>();
            entity.SoftDeleteInit(entity);
            List<UpdateDefinition<TEntity>> list = BuildUpdateDefinition(entity);
            UpdateDefinition<TEntity> updatefilter = Builders<TEntity>.Update.Combine(list);
            UpdateResult result;
            if (session == null)
            {
                result = Client(subTable).UpdateOne(filter, updatefilter);
            }
            else
            {
                result = Client(subTable).UpdateOne(session, filter, updatefilter);
            }

            bool flag = result.IsAcknowledged;
            if (flag)
            {
                flag = result.ModifiedCount > 0;
            }
            return flag;
        }



        /// <summary>
        /// 异步逻辑删除多条数据（异步）(分表)
        /// </summary>
        /// <param name="filter">删除的条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public bool SoftDelete(Expression<Func<TEntity, bool>> filter, object subTable = null, IClientSessionHandle session = null)
        {
            filter = ExpressionIsDelete(filter);
            EntityBase<TKey> entity = new EntityBase<TKey>();
            entity.SoftDeleteInit(entity);
            List<UpdateDefinition<TEntity>> list = BuildUpdateDefinition(entity);
            UpdateDefinition<TEntity> updatefilter = Builders<TEntity>.Update.Combine(list);
            UpdateResult result = null;
            if (session == null)
            {
                result = Client(subTable).UpdateMany(filter, updatefilter);
            }
            else
            {
                result = Client(subTable).UpdateMany(session, filter, updatefilter);
            }

            bool flag = result.IsAcknowledged;
            if (flag)
            {
                flag = result.ModifiedCount > 0;
            }
            return flag;
        }


        /// <summary>
        /// 异步物理删除一条数据（不推荐）（异步）(分表)
        /// </summary>
        /// <param name="id">原生Id</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public bool Delete(TKey id, object subTable = null, IClientSessionHandle session = null)
        {
            //修改条件
            FilterDefinition<TEntity> filter = Builders<TEntity>.Filter.Eq("Id", id);
            DeleteResult result = null;
            if (session == null)
            {
                result = Client(subTable).DeleteOne(filter);
            }
            else
            {
                result = Client(subTable).DeleteOne(session, filter);
            }

            bool flag = result.IsAcknowledged;
            if (flag)
            {
                flag = result.DeletedCount > 0;
            }
            return flag;
        }


        /// <summary>
        /// 异步物理删除多条数据（不推荐）（异步）(分表)
        /// </summary>
        /// <param name="filter">删除的条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public bool Delete(Expression<Func<TEntity, bool>> filter, object subTable = null, IClientSessionHandle session = null)
        {
            filter = ExpressionIsDelete(filter);
            DeleteResult result = null;
            if (session == null)
            {
                result = Client(subTable).DeleteMany(filter);
            }
            else
            {
                result = Client(subTable).DeleteMany(session, filter);
            }

            bool flag = result.IsAcknowledged;
            if (flag)
            {
                flag = result.DeletedCount > 0;
            }
            return flag;
        }


        /// <summary>
        /// 异步逻辑删除一条数据（异步）(分表)
        /// </summary>
        /// <param name="id">原生Id</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public async Task<bool> SoftDeleteAsync(TKey id, object subTable = null, IClientSessionHandle session = null)
        {
            //删除条件
            FilterDefinition<TEntity> filter = Builders<TEntity>.Filter.Eq("Id", id);
            EntityBase<TKey> entity = new EntityBase<TKey>();
            entity.SoftDeleteInit(entity);
            List<UpdateDefinition<TEntity>> list = BuildUpdateDefinition(entity);
            UpdateDefinition<TEntity> updatefilter = Builders<TEntity>.Update.Combine(list);
            UpdateResult result;
            if (session == null)
            {
                result = await Client(subTable).UpdateOneAsync(filter, updatefilter);
            }
            else
            {
                result = await Client(subTable).UpdateOneAsync(session, filter, updatefilter);
            }

            bool flag = result.IsAcknowledged;
            if (flag)
            {
                flag = result.ModifiedCount > 0;
            }
            return flag;
        }



        /// <summary>
        /// 异步逻辑删除多条数据（异步）(分表)
        /// </summary>
        /// <param name="filter">删除的条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public async Task<bool> SoftDeleteAsync(Expression<Func<TEntity, bool>> filter, object subTable = null, IClientSessionHandle session = null)
        {
            filter = ExpressionIsDelete(filter);
            EntityBase<TKey> entity = new EntityBase<TKey>();
            entity.SoftDeleteInit(entity);
            List<UpdateDefinition<TEntity>> list = BuildUpdateDefinition(entity);
            UpdateDefinition<TEntity> updatefilter = Builders<TEntity>.Update.Combine(list);
            UpdateResult result = null;
            if (session == null)
            {
                result = await Client(subTable).UpdateManyAsync(filter, updatefilter);
            }
            else
            {
                result = await Client(subTable).UpdateManyAsync(session, filter, updatefilter);
            }

            bool flag = result.IsAcknowledged;
            if (flag)
            {
                flag = result.ModifiedCount > 0;
            }
            return flag;
        }


        /// <summary>
        /// 异步物理删除一条数据（不推荐）（异步）(分表)
        /// </summary>
        /// <param name="id">原生Id</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public async Task<bool> DeleteAsync(TKey id, object subTable = null, IClientSessionHandle session = null)
        {
            //修改条件
            FilterDefinition<TEntity> filter = Builders<TEntity>.Filter.Eq("Id", id);
            DeleteResult result = null;
            if (session == null)
            {
                result = await Client(subTable).DeleteOneAsync(filter);
            }
            else
            {
                result = await Client(subTable).DeleteOneAsync(session, filter);
            }

            bool flag = result.IsAcknowledged;
            if (flag)
            {
                flag = result.DeletedCount > 0;
            }
            return flag;
        }


        /// <summary>
        /// 异步物理删除多条数据（不推荐）（异步）(分表)
        /// </summary>
        /// <param name="filter">删除的条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public async Task<bool> DeleteAsync(Expression<Func<TEntity, bool>> filter, object subTable = null, IClientSessionHandle session = null)
        {
            filter = ExpressionIsDelete(filter);
            DeleteResult result = null;
            if (session == null)
            {
                result = await Client(subTable).DeleteManyAsync(filter);
            }
            else
            {
                result = await Client(subTable).DeleteManyAsync(session, filter);
            }

            bool flag = result.IsAcknowledged;
            if (flag)
            {
                flag = result.DeletedCount > 0;
            }
            return flag;
        }

        #endregion 删除

        #region 查询


        /// <summary>
        /// 查询单条记录
        /// </summary>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="sort">排序</param>
        /// <param name="field">查询字段</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public TEntity Get(Expression<Func<TEntity, bool>> filter, object subTable = null, string[] field = null, SortDefinition<TEntity> sort = null, IClientSessionHandle session = null)
        {
            if (!(CheckCollectionExists(subTable)))
            {
                return null;
            }
            filter = ExpressionIsDelete(filter);
            IFindFluent<TEntity, TEntity> result = null;
            if (session == null)
            {
                result = Client(subTable).Find(filter);
            }
            else
            {
                result = Client(subTable).Find(session, filter);
            }
            //排序
            if (sort != null)
            {
                result = result.Sort(sort);
            }
            //制定查询字段
            if (field != null)
            {
                List<ProjectionDefinition<TEntity>> fieldList = new List<ProjectionDefinition<TEntity>>();
                for (int i = 0; i < field.Length; i++)
                {
                    fieldList.Add(Builders<TEntity>.Projection.Include(field[i].ToString()));
                }
                ProjectionDefinition<TEntity> projection = Builders<TEntity>.Projection.Combine(fieldList);
                fieldList?.Clear();
                result = result.Project<TEntity>(projection);
            }
            return result.FirstOrDefault();
        }


        /// <summary>
        /// 查询集合
        /// </summary>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="sort">排序</param>
        /// <param name="field">查询字段</param>
        /// <param name="limitCount">数量</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public List<TEntity> Query(Expression<Func<TEntity, bool>> filter, object subTable = null, string[] field = null, SortDefinition<TEntity> sort = null, int limitCount = 0, IClientSessionHandle session = null)
        {
            if (!(CheckCollectionExists(subTable)))
            {
                return null;
            }
            filter = ExpressionIsDelete(filter);
            IFindFluent<TEntity, TEntity> result = null;
            if (session == null)
            {
                result = Client(subTable).Find(filter);
            }
            else
            {
                result = Client(subTable).Find(session, filter);
            }
            if (limitCount > 0)
            {
                result.Limit(limitCount);
            }
            //排序
            if (sort != null)
            {
                result = result.Sort(sort);
            }
            //制定查询字段
            if (field != null)
            {
                List<ProjectionDefinition<TEntity>> fieldList = new List<ProjectionDefinition<TEntity>>();
                for (int i = 0; i < field.Length; i++)
                {
                    fieldList.Add(Builders<TEntity>.Projection.Include(field[i].ToString()));
                }
                ProjectionDefinition<TEntity> projection = Builders<TEntity>.Projection.Combine(fieldList);
                fieldList?.Clear();
                result = result.Project<TEntity>(projection);
            }
            return result.ToList();
        }


        /// <summary>
        /// 分页获得集合
        /// 案例：GetList(t=>t.Level=="Info", t=>t, 1, 20, out rsCount)
        /// </summary>
        /// <param name="filter">查询条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="orderBy">排序</param>
        /// <param name="PageIndex">页码</param>
        /// <param name="PageSize">条数</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public PagerList<TEntity> GetList(Expression<Func<TEntity, bool>> filter, Expression<Func<TEntity, object>> orderBy = null, int PageIndex = 1, int PageSize = 20, Expression<Func<TEntity, TEntity>> selector = null, object subTable = null, IClientSessionHandle session = null)
        {
            if (!(CheckCollectionExists(subTable)))
            {
                return new PagerList<TEntity>();
            }
            filter = ExpressionIsDelete(filter);
            int total = 1;
            PagerList<TEntity> page = new PagerList<TEntity>() { PageIndex = PageIndex, PageSize = PageSize };
            IMongoCollection<TEntity> colleciton = Client(subTable);
            IMongoQueryable<TEntity> queryable = null;
            if (session == null)
            {
                queryable = colleciton.AsQueryable();
            }
            else
            {
                queryable = colleciton.AsQueryable(session);
            }
            if (filter == null)
            {
                total = queryable.Count();
            }
            else
            {
                total = queryable.Where(filter).Count();
            }

            int pageCount = total / PageSize + ((total % PageSize) > 0 ? 1 : 0);
            if (PageIndex > pageCount)
            {
                PageIndex = pageCount;
            }
            if (PageIndex <= 0)
            {
                PageIndex = 1;
            }
            if (orderBy == null)
            {
                orderBy = en => en.Id;
            }
            if (selector == null)
            {
                selector = en => en;
            }
            IMongoQueryable<TEntity> mq = null;

            if (session == null)
            {
                mq = colleciton.AsQueryable(new AggregateOptions { AllowDiskUse = true });
            }
            else
            {
                mq = colleciton.AsQueryable(session, new AggregateOptions { AllowDiskUse = true });
            }
            page.Data = mq.Where(filter).OrderByDescending(orderBy).Select(selector).Skip((PageIndex - 1) * PageSize).Take(PageSize).ToList();
            var totalPages = (int)Math.Ceiling(total / (double)PageSize);
            page.Total = total;
            page.TotalPages = totalPages;
            page.HasNextPages = PageIndex < totalPages;
            page.HasPrevPages = PageIndex - 1 > 0;
            return page;
        }




        /// <summary>
        /// Count
        /// </summary>
        /// <param name="filter">查询条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public int Count(Expression<Func<TEntity, bool>> filter, object subTable = null, IClientSessionHandle session = null)
        {
            filter = ExpressionIsDelete(filter);
            int total = 0;

            if (session == null)
            {
                total = Client(subTable).AsQueryable().Where(filter).Count();
            }
            else
            {
                total = Client(subTable).AsQueryable(session).Where(filter).Count();
            }
            return total;
        }


        /// <summary>
        /// 查询单条记录
        /// </summary>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="sort">排序</param>
        /// <param name="field">查询字段</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public async Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> filter, object subTable = null, string[] field = null, SortDefinition<TEntity> sort = null, IClientSessionHandle session = null)
        {
            if (!(await CheckCollectionExistsAsync(subTable)))
            {
                return null;
            }

            filter = ExpressionIsDelete(filter);

            IFindFluent<TEntity, TEntity> result = null;
            if (session == null)
            {
                result = Client(subTable).Find(filter);
            }
            else
            {
                result = Client(subTable).Find(session, filter);
            }
            //排序
            if (sort != null)
            {
                result = result.Sort(sort);
            }
            //制定查询字段
            if (field != null)
            {
                List<ProjectionDefinition<TEntity>> fieldList = new List<ProjectionDefinition<TEntity>>();
                for (int i = 0; i < field.Length; i++)
                {
                    fieldList.Add(Builders<TEntity>.Projection.Include(field[i].ToString()));
                }
                ProjectionDefinition<TEntity> projection = Builders<TEntity>.Projection.Combine(fieldList);
                fieldList?.Clear();
                result = result.Project<TEntity>(projection);
            }
            return await result.FirstOrDefaultAsync();
        }


        /// <summary>
        /// 查询集合
        /// </summary>
        /// <param name="filter">条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="sort">排序</param>
        /// <param name="field">查询字段</param>
        /// <param name="limitCount">数量</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public async Task<List<TEntity>> QueryAsync(Expression<Func<TEntity, bool>> filter, object subTable = null, string[] field = null, SortDefinition<TEntity> sort = null, int limitCount = 0, IClientSessionHandle session = null)
        {
            if (!(await CheckCollectionExistsAsync(subTable)))
            {
                return null;
            }

            filter = ExpressionIsDelete(filter);
            IFindFluent<TEntity, TEntity> result = null;
            if (session == null)
            {
                result = Client(subTable).Find(filter);
            }
            else
            {
                result = Client(subTable).Find(session, filter);
            }
            if (limitCount > 0)
            {
                result.Limit(limitCount);
            }
            //排序
            if (sort != null)
            {
                result = result.Sort(sort);
            }
            //制定查询字段
            if (field != null)
            {
                List<ProjectionDefinition<TEntity>> fieldList = new List<ProjectionDefinition<TEntity>>();
                for (int i = 0; i < field.Length; i++)
                {
                    fieldList.Add(Builders<TEntity>.Projection.Include(field[i].ToString()));
                }
                ProjectionDefinition<TEntity> projection = Builders<TEntity>.Projection.Combine(fieldList);
                fieldList?.Clear();
                result = result.Project<TEntity>(projection);
            }
            return await result.ToListAsync();
        }


        /// <summary>
        /// 分页获得集合
        /// 案例：GetList(t=>t.Level=="Info", t=>t, 1, 20, out rsCount)
        /// </summary>
        /// <param name="filter">查询条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="orderBy">排序</param>
        /// <param name="PageIndex">页码</param>
        /// <param name="PageSize">条数</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public async Task<PagerList<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> filter, Expression<Func<TEntity, object>> orderBy = null, int PageIndex = 1, int PageSize = 20, Expression<Func<TEntity, TEntity>> selector = null, object subTable = null, IClientSessionHandle session = null)
        {
            if (!(await CheckCollectionExistsAsync(subTable)))
            {
                return new PagerList<TEntity>();
            }

            filter = ExpressionIsDelete(filter);

            int total = 1;
            PagerList<TEntity> page = new PagerList<TEntity>() { PageIndex = PageIndex, PageSize = PageSize };
            IMongoCollection<TEntity> colleciton = Client(subTable);
            IMongoQueryable<TEntity> queryable = null;
            if (session == null)
            {
                queryable = colleciton.AsQueryable();
            }
            else
            {
                queryable = colleciton.AsQueryable(session);
            }
            total = await queryable.Where(filter).CountAsync();


            int pageCount = total / PageSize + ((total % PageSize) > 0 ? 1 : 0);
            if (PageIndex > pageCount)
            {
                PageIndex = pageCount;
            }
            if (PageIndex <= 0)
            {
                PageIndex = 1;
            }
            if (orderBy == null)
            {
                orderBy = en => en.Id;
            }
            if (selector == null)
            {
                selector = en => en;
            }


            IMongoQueryable<TEntity> mq = null;

            if (session == null)
            {
                mq = colleciton.AsQueryable(new AggregateOptions { AllowDiskUse = true });
            }
            else
            {
                mq = colleciton.AsQueryable(session, new AggregateOptions { AllowDiskUse = true });
            }
            page.Data = await mq.Where(filter).OrderByDescending(orderBy).Select(selector).Skip((PageIndex - 1) * PageSize).Take(PageSize).ToListAsync();
            var totalPages = (int)Math.Ceiling(total / (double)PageSize);
            page.Total = total;
            page.TotalPages = totalPages;
            page.HasNextPages = PageIndex < totalPages;
            page.HasPrevPages = PageIndex - 1 > 0;
            return page;
        }




        /// <summary>
        /// Count 异步方法
        /// </summary>
        /// <param name="filter">查询条件</param>
        /// <param name="subTable">分表业务对象（默认字符串后缀分表）</param>
        /// <param name="session">用于事务处理，非必填</param>
        /// <returns></returns>
        public async Task<int> CountAsync(Expression<Func<TEntity, bool>> filter, object subTable = null, IClientSessionHandle session = null)
        {
            filter = ExpressionIsDelete(filter);
            int total = 0;

            if (session == null)
            {
                total = await Client(subTable).AsQueryable().Where(filter).CountAsync();
            }
            else
            {
                total = await Client(subTable).AsQueryable(session).Where(filter).CountAsync();
            }
            return total;
        }

        #endregion

        #region 扩展方法

        /// <summary>
        /// 获取分表querytable
        /// </summary>
        /// <param name="subTableValue"></param>
        /// <returns></returns>
        protected virtual string GetTableName(object subTableValue) => _multiTableFactory.GetTableName(typeof(TEntity), subTableValue);
        /// <summary>
        /// 验证集合文档(表)是否存在
        /// </summary>
        /// <returns></returns>
        public bool CheckCollectionExists(object subTable = null)
        {
            string tableName = GetTableName(subTable);
            ListCollectionsOptions options = new ListCollectionsOptions
            {
                Filter = Builders<BsonDocument>.Filter.Eq("name", tableName)
            };
            IMongoDatabase database = _context.GetMongoDatabase();
            return (database.ListCollections(options)).ToEnumerable().Any();
        }/// <summary>
         /// 验证集合文档(表)是否存在
         /// </summary>
         /// <returns></returns>
        public async Task<bool> CheckCollectionExistsAsync(object subTable = null)
        {
            string tableName = GetTableName(subTable);
            ListCollectionsOptions options = new ListCollectionsOptions
            {
                Filter = Builders<BsonDocument>.Filter.Eq("name", tableName)
            };
            IMongoDatabase database = _context.GetMongoDatabase();
            return (await database.ListCollectionsAsync(options)).ToEnumerable().Any();
        }

        /// <summary>
        /// 添加逻辑删除
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public Expression<Func<TEntity, bool>> ExpressionIsDelete(Expression<Func<TEntity, bool>> whereExpression)
        {
            Expression<Func<TEntity, bool>> isDelete = it => !it.IsDeleted;
            if (whereExpression == null)
            {
                whereExpression = isDelete;
            }
            else
            {
                whereExpression = isDelete.And(whereExpression);
            }
            return whereExpression;
        }

        #endregion
    }
}